package com.canaan.business.service.quality.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.canaan.business.common.enums.quality.QualityResultEnum;
import com.canaan.business.common.enums.quality.QualityTaskStatusEnum;
import com.canaan.business.common.enums.quality.QualityValueTypeEnum;
import com.canaan.business.domain.quality.ProductQualityItem;
import com.canaan.business.domain.quality.ProductQualityMainTask;
import com.canaan.business.domain.storehouse.WmsBarcodeRecord;
import com.canaan.business.service.quality.IProductQualityItemService;
import com.canaan.business.service.quality.IProductQualityMainTaskService;
import com.canaan.business.service.storehouse.IWmsBarcodeRecordService;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.SecurityUtils;
import com.canaan.common.utils.TableNoUtil;
import com.canaan.common.utils.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import com.canaan.business.mapper.quality.ProductQualityTaskDetailMapper;
import com.canaan.business.domain.quality.ProductQualityTaskDetail;
import com.canaan.business.service.quality.IProductQualityTaskDetailService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 物料质检任务明细Service业务层处理
 *
 * @author ruoyi
 * @date 2023-02-07
 */
@Service
public class ProductQualityTaskDetailServiceImpl implements IProductQualityTaskDetailService {
    @Resource
    private ProductQualityTaskDetailMapper productQualityTaskDetailMapper;
    @Resource
    private IProductQualityMainTaskService qualityMainTaskService;
    @Resource
    private IProductQualityItemService productQualityItemService;
    @Resource
    private IWmsBarcodeRecordService barcodeRecordService;

    /**
     * 查询物料质检任务明细
     *
     * @param id 物料质检任务明细主键
     * @return 物料质检任务明细
     */
    @Override
    public ProductQualityTaskDetail selectProductQualityTaskDetailById(Long id) {
        return productQualityTaskDetailMapper.selectProductQualityTaskDetailById(id);
    }

    /**
     * 查询物料质检任务明细列表
     *
     * @param productQualityTaskDetail 物料质检任务明细
     * @return 物料质检任务明细
     */
    @Override
    public List<ProductQualityTaskDetail> selectProductQualityTaskDetailList(ProductQualityTaskDetail productQualityTaskDetail) {
        return productQualityTaskDetailMapper.selectProductQualityTaskDetailList(productQualityTaskDetail);
    }

    /**
     * 新增物料质检任务明细
     *
     * @param productQualityTaskDetail 物料质检任务明细
     * @return 结果
     */
    @Override
    public int insertProductQualityTaskDetail(ProductQualityTaskDetail productQualityTaskDetail) {
        if(StringUtils.isBlank(productQualityTaskDetail.getNo())){
            productQualityTaskDetail.setNo(TableNoUtil.getNo(ProductQualityTaskDetail.class));
        }
        productQualityTaskDetail.setCreateBy(SecurityUtils.getUsername());
        productQualityTaskDetail.setCreateTime(DateUtils.getNowDate());
        return productQualityTaskDetailMapper.insertProductQualityTaskDetail(productQualityTaskDetail);
    }

    /**
     * 批量新增物料质检任务明细
     *
     * @param productQualityTaskDetailList 物料质检任务明细列表
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchInsertProductQualityTaskDetail(List<ProductQualityTaskDetail> productQualityTaskDetailList) {

        List<ProductQualityTaskDetail> addList = new ArrayList<>();
        List<ProductQualityTaskDetail> editList = new ArrayList<>();

        String username = SecurityUtils.getUsername();
        Date currentTime = DateUtils.getNowDate();
        // 存储文档中的条码数量，用于判断检验的个数
        List<String> barcodeList = new ArrayList<>();
        // 新增的已检数量
        BigDecimal addBarcodeNum = BigDecimal.ZERO;
        // 判断必填项是否全部填写，如果ID为空，则新增，ID不为空则编辑
        for (ProductQualityTaskDetail productQualityTaskDetail : productQualityTaskDetailList){
            this.checkAllInput(productQualityTaskDetail);
            if (productQualityTaskDetail.getId() == null){
                if(StringUtils.isBlank(productQualityTaskDetail.getNo())){
                    productQualityTaskDetail.setNo(TableNoUtil.getNo(ProductQualityTaskDetail.class));
                }
                productQualityTaskDetail.setCreateBy(username);
                productQualityTaskDetail.setCreateTime(currentTime);
                addList.add(productQualityTaskDetail);
                addBarcodeNum = addBarcodeNum.add(productQualityTaskDetail.getBarcodeQty());
            }else {
                editList.add(productQualityTaskDetail);
            }
            if (!barcodeList.contains(productQualityTaskDetail.getBarcode())){
                barcodeList.add(productQualityTaskDetail.getBarcode());
            }

        }
        int insertNum = 0;

        if (!CollectionUtils.isEmpty(addList)){

            for (int i=0; i<addList.size();) {
                int endIndex = i+500;
                if (endIndex > addList.size()) {
                    endIndex = addList.size();
                }
                insertNum = insertNum + productQualityTaskDetailMapper.batchInsertProductQualityTaskDetail(addList.subList(i, endIndex));
                i = endIndex;
            }
        }
        if (!CollectionUtils.isEmpty(editList)){
            this.batchUpdateProductQualityTaskDetail(editList);
        }

        // 修改主表的状态、已检验数量
        ProductQualityMainTask mainTask = qualityMainTaskService.selectProductQualityMainTaskByNo(productQualityTaskDetailList.get(0).getTaskNo());
        mainTask.setInspectedQuantity(mainTask.getInspectedQuantity().add(addBarcodeNum));
        mainTask.setStatus(QualityTaskStatusEnum.INSPECTION.getCode());
        qualityMainTaskService.updateProductQualityMainTask(mainTask);
        // 防止返回code500，直接在insertNum上加1
        insertNum += 1;
        return insertNum;
    }

    /**
     * 校验全部必填项是否填写，赋值检验结果
     *
     * @param productQualityTaskDetail 物料质检任务明细
     */
    private void checkAllInput(ProductQualityTaskDetail productQualityTaskDetail){
        if (StringUtils.isEmpty(productQualityTaskDetail.getItemNo()) || StringUtils.isEmpty(productQualityTaskDetail.getItemName())){
            throw new ServiceException("质检项不能为空");
        }
        if (StringUtils.isEmpty(productQualityTaskDetail.getValueType())){
            throw new ServiceException("质检项值类型不能为空");
        }
        // 2023-07-10 代码调整，根据前端传的值判断是否要校验实际值，不需要校验且未填的，默认为合格
        if (productQualityTaskDetail.getWhetherPass() && StringUtils.isEmpty(productQualityTaskDetail.getActualValue())){
            productQualityTaskDetail.setQualityResult(QualityResultEnum.OK.getCode());
        }
        else {
            if (StringUtils.isEmpty(productQualityTaskDetail.getActualValue())){
                throw new ServiceException("实际值不能为空");
            }
            if (QualityValueTypeEnum.RANGE.getCode().equals(productQualityTaskDetail.getValueType())){
                if (productQualityTaskDetail.getLowerLimitValue() == null || productQualityTaskDetail.getUpperLimitValue() == null){
                    throw new ServiceException("质检项值类型为范围值，标准值上下限不能为空");
                }
                BigDecimal actualValue = new BigDecimal(productQualityTaskDetail.getActualValue());
                if (productQualityTaskDetail.getLowerLimitValue().compareTo(actualValue) <= 0
                        && productQualityTaskDetail.getUpperLimitValue().compareTo(actualValue) >= 0
                ){
                    productQualityTaskDetail.setQualityResult(QualityResultEnum.OK.getCode());
                }else {
                    productQualityTaskDetail.setQualityResult(QualityResultEnum.NG.getCode());
                }
            }
        }


        if (QualityValueTypeEnum.STATUS.getCode().equals(productQualityTaskDetail.getValueType())){
            productQualityTaskDetail.setQualityResult(productQualityTaskDetail.getActualValue());
        }

        if (StringUtils.isEmpty(productQualityTaskDetail.getTaskNo())){
            throw new ServiceException("质检任务编号不能为空");
        }

        if (StringUtils.isEmpty(productQualityTaskDetail.getQualityResult())){
            throw new ServiceException("检验结果不能为空");
        }
    }

    /**
     * 修改物料质检任务明细
     *
     * @param productQualityTaskDetail 物料质检任务明细
     * @return 结果
     */
    @Override
    public int updateProductQualityTaskDetail(ProductQualityTaskDetail productQualityTaskDetail) {
        productQualityTaskDetail.setUpdateBy(SecurityUtils.getUsername());
        productQualityTaskDetail.setUpdateTime(DateUtils.getNowDate());
        return productQualityTaskDetailMapper.updateProductQualityTaskDetail(productQualityTaskDetail);
    }

    /**
     * 批量修改物料质检任务明细
     *
     * @param productQualityTaskDetailList 物料质检任务明细列表
     * @return 结果
     */
    @Override
    public int batchUpdateProductQualityTaskDetail(List<ProductQualityTaskDetail> productQualityTaskDetailList) {
        String username = SecurityUtils.getUsername();
        Date currerTime = DateUtils.getNowDate();
        for (ProductQualityTaskDetail productQualityTaskDetail : productQualityTaskDetailList){
            productQualityTaskDetail.setUpdateBy(username);
            productQualityTaskDetail.setUpdateTime(currerTime);
        }
        int updateNum = 0;
        for (int i=0; i<productQualityTaskDetailList.size();) {
            int endIndex = i+500;
            if (endIndex > productQualityTaskDetailList.size()) {
                endIndex = productQualityTaskDetailList.size();
            }
            updateNum = updateNum + productQualityTaskDetailMapper.batchUpdateProductQualityTaskDetail(productQualityTaskDetailList.subList(i, endIndex));
            i = endIndex;
        }
        return updateNum;
    }

    /**
     * 批量删除物料质检任务明细
     *
     * @param ids 需要删除的物料质检任务明细主键集合
     * @return 结果
     */
    @Override
    public int deleteProductQualityTaskDetailByIds(Long[] ids) {
        return productQualityTaskDetailMapper.deleteProductQualityTaskDetailByIds(ids);
    }

    /**
     * 删除物料质检任务明细信息
     *
     * @param id 物料质检任务明细主键
     * @return 结果
     */
    @Override
    public int deleteProductQualityTaskDetailById(Long id) {
        return productQualityTaskDetailMapper.deleteProductQualityTaskDetailById(id);
    }

    /**
     * 查询物料质检任务明细
     *
     * @param no 编号
     * @return 物料质检任务明细
     */
    @Override
    public ProductQualityTaskDetail selectProductQualityTaskDetailByNo(String no) {
        return productQualityTaskDetailMapper.selectProductQualityTaskDetailByNo(no);
    }

    /**
     * 批量删除物料质检任务明细
     *
     * @param nos 需要删除的编号集合
     * @return 结果
     */
    @Override
    public int deleteProductQualityTaskDetailByNos(String[] nos) {
        return productQualityTaskDetailMapper.deleteProductQualityTaskDetailByNos(nos);
    }

    /**
     * 删除物料质检任务明细信息
     *
     * @param no 编号
     * @return 结果
     */
    @Override
    public int deleteProductQualityTaskDetailByNo(String no) {
        return productQualityTaskDetailMapper.deleteProductQualityTaskDetailByNo(no);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importData(List<ProductQualityTaskDetail> fileDataList,String taskNo) {
        if (StringUtils.isNull(fileDataList) || fileDataList.size() == 0) {
            throw new ServiceException("导入数据不能为空！");
        }
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        // 循环列表判断是否是空
        for (int i = 0; i < fileDataList.size(); i++) {
            ProductQualityTaskDetail fileEntity = fileDataList.get(i);
            int rowNum = i + 2;
            if (StringUtils.isEmpty(fileEntity.getBarcode())){
                failureNum++;
                failureMsg.append("第" + rowNum + "行条码不能为空");
                break;
            }
            if (StringUtils.isEmpty(fileEntity.getItemName())){
                failureNum++;
                failureMsg.append("第" + rowNum + "行质检项名称不能为空");
                break;
            }
            if (StringUtils.isEmpty(fileEntity.getActualValue())){
                failureNum++;
                failureMsg.append("第" + rowNum + "行实际值不能为空");
                break;
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！");
            throw new ServiceException(failureMsg.toString());
        }
        // 根据taskNo查询质检任务，并查询物料质检项
        ProductQualityMainTask mainTask = this.qualityMainTaskService.selectProductQualityMainTaskByNo(taskNo);
        ProductQualityItem searchItem = new ProductQualityItem();
        searchItem.setProductNo(mainTask.getProductNo());
        List<ProductQualityItem> taskItems = this.productQualityItemService.selectProductQualityItemList(searchItem);
        if (CollectionUtils.isEmpty(taskItems)){
            failureMsg.insert(0, "导入失败！");
            throw new ServiceException("质检任务对应物料不存在检验项");
        }
        // 查询质检任务明细，判断是否条码存在重复
        ProductQualityTaskDetail searchDetail = new ProductQualityTaskDetail();
        searchDetail.setTaskNo(taskNo);
        List<ProductQualityTaskDetail> qualityTaskDetailList = this.selectProductQualityTaskDetailList(searchDetail);
        List<String> detailBarcodeList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(qualityTaskDetailList)){
            detailBarcodeList = qualityTaskDetailList.stream().map(ProductQualityTaskDetail::getBarcode).distinct().collect(Collectors.toList());
        }

        // 判断Excel条码是否都存在
        List<String> fileBarcodeList = fileDataList.stream().map(ProductQualityTaskDetail::getBarcode).distinct().collect(Collectors.toList());
        WmsBarcodeRecord searchBarcode = new WmsBarcodeRecord();
        searchBarcode.setBarCodes(fileBarcodeList);
        List<WmsBarcodeRecord> barcodeRecordList = this.barcodeRecordService.selectWmsBarcodeRecordList(searchBarcode);
        Map<String,WmsBarcodeRecord> barcodeMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(barcodeRecordList)){
            barcodeMap = barcodeRecordList.stream().collect(Collectors.toMap(WmsBarcodeRecord::getBarCode, Function.identity(), (key1, key2) -> key2));
        }

        Map<String,ProductQualityItem> taskItemMap = taskItems.stream().collect(Collectors.toMap(ProductQualityItem::getItemName, Function.identity(), (key1, key2) -> key2));
        // 数据按条码分组，判断是否物料的每个质检项都有导入
        Map<String,List<ProductQualityTaskDetail>> fileGroupMap = fileDataList.stream().collect(Collectors.groupingBy(ProductQualityTaskDetail::getBarcode));
        for (String barCode : fileGroupMap.keySet()) {
            // 文档中该条码的质检项目
            List<ProductQualityTaskDetail> codeFileItems  = fileGroupMap.get(barCode);
            if (codeFileItems.size() != taskItems.size()){
                failureMsg.insert(0, "导入失败！");
                throw new ServiceException("条码[" + barCode + "]对应的质检项不准确");
            }
            // 判断是否条码已经质检
            if (detailBarcodeList.contains(barCode)){
                throw new ServiceException("条码[" + barCode + "]已存在，请修改后提交");
            }
            // 循环判断是否每个质检项在文档中都有输入
            for (ProductQualityItem taskItem : taskItems) {
                boolean isInput = false;
                for (ProductQualityTaskDetail codeFileItem : codeFileItems) {
                    if (codeFileItem.getItemName().equals(taskItem.getItemName())){
                        isInput = true;
                    }
                }
                if (!isInput){
                    failureMsg.insert(0, "导入失败！");
                    throw new ServiceException("条码[" + barCode +  "]缺少[" + taskItem.getItemName() +  "]质检任务");
                }
            }
        }

        // 循环每个检验项目，赋值和计算质检结果，是状态值时，需要输入NG或OK
        for (ProductQualityTaskDetail productQualityTaskDetail : fileDataList) {
            WmsBarcodeRecord barcodeRecord = barcodeMap.get(productQualityTaskDetail.getBarcode());
            // 判断条码是否在条码记录表中
            if (barcodeRecord == null || !barcodeRecord.getProductNo().equals(mainTask.getProductNo())){
                throw new ServiceException("条码[" + productQualityTaskDetail.getBarcode() + "]输入有误，请修改后提交");
            }
            productQualityTaskDetail.setBarcodeQty(new BigDecimal(barcodeRecord.getQuantity()));
            ProductQualityItem qualityItem = taskItemMap.get(productQualityTaskDetail.getItemName());
            if (QualityValueTypeEnum.STATUS.getCode().equals(qualityItem.getValueType())){
                if (!QualityResultEnum.OK.getCode().equals(productQualityTaskDetail.getActualValue())
                        && !QualityResultEnum.NG.getCode().equals(productQualityTaskDetail.getActualValue())
                ){
                    failureMsg.insert(0, "导入失败！");
                    throw new ServiceException("条码[" + productQualityTaskDetail.getBarcode() +  "]的质检项[" + productQualityTaskDetail.getItemName() +  "]值类型为状态值，实际值需要为NG或OK");
                }else {
                    productQualityTaskDetail.setQualityResult(productQualityTaskDetail.getActualValue());
                }
            }
            if (QualityValueTypeEnum.RANGE.getCode().equals(qualityItem.getValueType())){
                BigDecimal actualValue;
                try {
                    actualValue = new BigDecimal(productQualityTaskDetail.getActualValue());
                }
                catch (NumberFormatException e){
                    throw new ServiceException("条码[" + productQualityTaskDetail.getBarcode() +  "]的质检项[" + productQualityTaskDetail.getItemName() +  "]值类型为范围值，实际值需要为数值");
                }
                if (qualityItem.getLowerLimitValue().compareTo(actualValue) <= 0
                        && qualityItem.getUpperLimitValue().compareTo(actualValue) >= 0
                ){
                    productQualityTaskDetail.setQualityResult(QualityResultEnum.OK.getCode());
                }else {
                    productQualityTaskDetail.setQualityResult(QualityResultEnum.NG.getCode());
                }
            }
            productQualityTaskDetail.setTaskNo(taskNo);
            productQualityTaskDetail.setItemNo(qualityItem.getNo());
            productQualityTaskDetail.setMethod(qualityItem.getMethod());
            productQualityTaskDetail.setValueType(qualityItem.getValueType());
            productQualityTaskDetail.setLowerLimitValue(qualityItem.getLowerLimitValue());
            productQualityTaskDetail.setUpperLimitValue(qualityItem.getUpperLimitValue());
        }
        this.batchInsertProductQualityTaskDetail(fileDataList);
        int addCount = fileDataList.size();
        successMsg.insert(0, "导入成功！共新增 " + addCount + " 条数据");

        return successMsg.toString();
    }
}
